package com.wkr.order.config;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.dianping.cat.Cat;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
 * 自定义负载均衡规则
 */
@Slf4j
public class LBRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties discoveryProperties;

    private static int count = 0;

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
    }

    @Override
    public Server choose(Object key) {
        return weightChoose();
    }

    public Server customChoose() {
        ILoadBalancer loadBalancer = getLoadBalancer();
        if (null == loadBalancer) {
            return null;
        }

        Server server;
        List<Server> upServer = loadBalancer.getReachableServers();
        List<Server> allServer = loadBalancer.getAllServers();
        int upServerCount = upServer.size();
        int allServerCount = allServer.size();
        if (upServerCount == 0 || allServerCount == 0) {
            return null;
        }
        if (upServer.size() < 2) {
            return upServer.get(0);
        }
        count++;
        if (count < 2) {
            server = upServer.get(0);
        } else {
            server = upServer.get(1);
        }
        if (count >= 4) {
            count = 0;
        }
        return server;
    }

    /**
     * 权重负载均衡
     */
    public Server weightChoose() {
        try{
            long startTime = System.currentTimeMillis();
            // 调用父类方法, 获取当前使用的负载均衡器
            BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
            // 获取当前服务的名称
            String serviceName = baseLoadBalancer.getName();

            /**
             * namingService: 获取nacos的服务发现API
             */
            NamingService namingService = discoveryProperties.namingServiceInstance();

            /**
             * 根据名称获取服务发现实例
             * 在selectOneHealthyInstance中, nacos实现了权重的负载均衡算法
             */
            Instance instance = namingService.selectOneHealthyInstance(serviceName);
            log.info("port:" + instance.getPort());
            long endTime = System.currentTimeMillis();
            long useTime = endTime - startTime;
            log.info("useLBms:" + useTime);
            Cat.logMetricForCount("useLBms", (int)useTime);
            return new NacosServer(instance);
        } catch (NacosException e) {
            e.printStackTrace();
        }
        return null;
    }
}
